package com.qkun.library.utils;

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.text.TextUtils;

import androidx.core.os.EnvironmentCompat;
import androidx.core.util.Pair;

import com.qkun.library.base.BaseApplication;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;

public final class StorageUtils {

    private static final String TAG = "StorageUtils";

    private StorageUtils() {
    }

    public static File getSdcard() {
        return isSdcardMounted() ? Environment.getExternalStorageDirectory() : null;
    }

    public static String getSdcardPath() {
        String sdcardPath = "";
        File sdcard = getSdcard();
        if (Utils.nonNull(sdcard)) {
            sdcardPath = sdcard.getPath();
        }
        MyLog.d(TAG, "SdcardPath: " + sdcardPath);
        return sdcardPath;
    }

    public static String getSdcardAbsolutePath() {
        String sdcardAbsolutePath = "";
        File sdcard = getSdcard();
        if (Utils.nonNull(sdcard)) {
            sdcardAbsolutePath = sdcard.getAbsolutePath();
        }
        MyLog.d(TAG, "SdcardAbsolutePath: " + sdcardAbsolutePath);
        return sdcardAbsolutePath;
    }

    /**
     * 返回特定类型的目录
     *
     * @param type The type of storage directory to return. Should be one of
     *             {@link Environment#DIRECTORY_MUSIC 音乐保存的位置},
     *             {@link Environment#DIRECTORY_PODCASTS 用于保存podcast(博客)的音频文件},
     *             {@link Environment#DIRECTORY_RINGTONES 保存铃声的位置},
     *             {@link Environment#DIRECTORY_ALARMS 将音频文件放置在用户可以选择的警报列表中的标准目录（不是常规音乐）},
     *             {@link Environment#DIRECTORY_NOTIFICATIONS 通知音保存的位置},
     *             {@link Environment#DIRECTORY_PICTURES 下载的图片保存的位置},
     *             {@link Environment#DIRECTORY_MOVIES 电影保存的位置， 比如 通过google play下载的电影},
     *             {@link Environment#DIRECTORY_DOWNLOADS 下载文件保存的位置},
     *             {@link Environment#DIRECTORY_DCIM 相机拍摄的图片和视频保存的位置},
     *             {@link Environment#DIRECTORY_DOCUMENTS 用于放置用户创建的文档}.
     *             May not be null.
     * @return
     */
    public static File getPublicDirectory(String type) {
        File publicDirectory = Environment.getExternalStoragePublicDirectory(type);
        if (isMounted(publicDirectory)) {
            return publicDirectory;
        }
        return null;
    }

    public static String getPublicDirectoryPath(String type) {
        String publicDirectoryPath = "";
        File publicDirectory = getPublicDirectory(type);
        if (Utils.nonNull(publicDirectory)) {
            publicDirectoryPath = publicDirectory.getPath();
        }
        MyLog.d(TAG, "PublicDirectoryPath: " + publicDirectoryPath);
        return publicDirectoryPath;
    }

    public static String getPublicDirectoryAbsolutePath(String type) {
        String publicDirectoryAbsolutePath = "";
        File publicDirectory = getPublicDirectory(type);
        if (Utils.nonNull(publicDirectory)) {
            publicDirectoryAbsolutePath = publicDirectory.getAbsolutePath();
        }
        MyLog.d(TAG, "PublicDirectoryAbsolutePath: " + publicDirectoryAbsolutePath);
        return publicDirectoryAbsolutePath;
    }

    /**
     * 获取 Android 数据目录
     *
     * @return
     */
    public static File getDataDirectory() {
        File dataDirectory = Environment.getDataDirectory();
        if (isMounted(dataDirectory)) {
            return dataDirectory;
        }
        return null;
    }

    /**
     * 获取 Android 的根目录
     *
     * @return
     */
    public static File getRootDirectory() {
        File rootDirectory = Environment.getRootDirectory();
        if (isMounted(rootDirectory)) {
            return rootDirectory;
        }
        return null;
    }

    /**
     * 获取 Android 下载/缓存内容目录
     *
     * @return
     */
    public static File getDownloadCacheDirectory() {
        File downloadCacheDirectory = Environment.getDownloadCacheDirectory();
        if (isMounted(downloadCacheDirectory)) {
            return downloadCacheDirectory;
        }
        return null;
    }

    /**
     * 获取存储器列表
     *
     * @return
     */
    public static String[] getStorageList() {
        StorageManager storageManager = (StorageManager) BaseApplication.getAppContext().getSystemService(Context.STORAGE_SERVICE);
        String[] storageList = null;
        try {
            Method getVolumePaths = StorageManager.class.getMethod("getVolumePaths");
            storageList = (String[]) getVolumePaths.invoke(storageManager);
        } catch (NoSuchMethodException e) {
            MyLog.e(e);
        } catch (IllegalAccessException e) {
            MyLog.e(e);
        } catch (InvocationTargetException e) {
            MyLog.e(e);
        }
        return storageList;
    }

    public static boolean isSdcardMounted() {
        return Environment.MEDIA_MOUNTED.equals(getSdcardState());
    }

    public static boolean isMounted(File path) {
        return Environment.MEDIA_MOUNTED.equals(getStorageState(path));
    }

    public static String getSdcardState() {
        String sdcardState = Environment.getExternalStorageState();
        inputStorageStateMassage(sdcardState);
        return sdcardState;
    }

    public static String getStorageState(File path) {
        String storageState = EnvironmentCompat.getStorageState(path);
        inputStorageStateMassage(storageState);
        return storageState;
    }

    private static void inputStorageStateMassage(String storageState) {
        switch (storageState) {
            case Environment.MEDIA_BAD_REMOVAL:
                MyLog.d(TAG, "Sdcard被卸载前己被移除。");
                break;
            case Environment.MEDIA_CHECKING:
                MyLog.d(TAG, "Sdcard存在但正在进行磁盘检查。");
                break;
            case Environment.MEDIA_MOUNTED:
                MyLog.d(TAG, "Sdcard存在并被挂载且具有读/写权限。");
                break;
            case Environment.MEDIA_MOUNTED_READ_ONLY:
                MyLog.d(TAG, "Sdcard存在并被挂载但只具有只读权限。");
                break;
            case Environment.MEDIA_NOFS:
                MyLog.d(TAG, "Sdcard存在但为空或正在使用不受支持的文件系统。");
                break;
            case Environment.MEDIA_REMOVED:
                MyLog.d(TAG, "Sdcard不存在。");
                break;
            case Environment.MEDIA_SHARED:
                MyLog.d(TAG, "Sdcard未挂载，并通过USB大容量存储共享。");
                break;
            case Environment.MEDIA_UNMOUNTABLE:
                MyLog.d(TAG, "Sdcard存在但不可以被挂载。通常，如果Sdcard上的文件系统已损坏，则会发生这种情况。");
                break;
            case Environment.MEDIA_UNMOUNTED:
                MyLog.d(TAG, "Sdcard存在但没有被挂载。");
                break;
            default:
                MyLog.d(TAG, "StorageState: " + storageState);
        }
    }

    public static long[] getSdcardUsage() {
        long[] result = new long[2];
        String sdcardPath = getSdcardPath();
        if (!TextUtils.isEmpty(sdcardPath)) {
            //StatFs是模拟linux df命令的一个类，用于获得Sdcard卡和手机内存的使用情况
            StatFs statfs = new StatFs(sdcardPath);
            //文件系统上块的大小（以字节为单位）
            long blockSize;
            //文件系统上的总块数
            long blockCount;
            //文件系统上可用的块数量，可供应用程序使用
            long availableBlocks;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                blockSize = statfs.getBlockSizeLong();
                blockCount = statfs.getBlockCountLong();
                availableBlocks = statfs.getAvailableBlocksLong();
            } else {
                blockSize = statfs.getBlockSize();
                blockCount = statfs.getBlockCount();
                availableBlocks = statfs.getAvailableBlocks();
            }
            result[0] = blockCount * blockSize;
            result[1] = availableBlocks * blockSize;
        }
        MyLog.d(TAG, "SD卡总大小(bytes)：" + result[0] + " SD卡可用大小(bytes)：" + result[1]);
        return result;
    }

    /**
     * 格式化存储大小
     *
     * @param size
     * @return
     */
    public static Pair<String, String> formatStorageSize(long size) {
        if (size < 0) size = 0;
        String level = "B";
        if (size >= 1024) {
            size /= 1024;
            level = "KB";
            if (size >= 1024) {
                size /= 1024;
                level = "MB";
                if (size >= 1024) {
                    size /= 1024;
                    level = "GB";
                }
            }
        }
        DecimalFormat formatter = new DecimalFormat();
        //每3个数字用,分隔如：1,000
        formatter.setGroupingSize(3);
        return Pair.create(formatter.format(size), level);
    }

}
